

#import "BIDRepositoryViewController.h"
#import "BIDRepository.h"
#import "BIDAppDelegate.h"
#import "stdlib.h"
#import "svn_client_log_ios.h"

@interface BIDRepositoryViewController ()

@end

@implementation BIDRepositoryViewController

- (NSString *)dataFilePath{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentDirectory = [paths objectAtIndex:0];
    return [documentDirectory stringByAppendingPathComponent:@"data.archive"];
}
- (void)viewDidLoad{
    [super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
	// Do any additional setup after loading the view.
    self.repository.textColor = [UIColor blueColor];
    self.repository.font = [UIFont boldSystemFontOfSize:25];
    self.repository.shadowColor = [UIColor blueColor];
    self.repository.shadowOffset = CGSizeMake(-2, -2);
    self.repository.text = @"none";
    NSString *filePath = [self dataFilePath];
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
        NSData *data = [[NSMutableData alloc] initWithContentsOfFile:filePath];
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        BIDRepository *repository = [unarchiver decodeObjectForKey:@"repository"];
        [unarchiver finishDecoding];
        self.repository.text = repository.name;
        if (repository.url != nil && repository.loginname != nil && repository.password != nil ){
            strcpy(repositoryForLogFetch.url,[repository.url UTF8String]);
            strcpy(repositoryForLogFetch.loginname,[repository.loginname UTF8String]);
            strcpy(repositoryForLogFetch.password,[repository.password UTF8String]);
        }
    }
    UIButton *buttonDownload = (id)[self.view viewWithTag:1];
    if ([self.repository.text isEqualToString:@"none"]){
        //NSLog(@"repository name: %@", self.repository.text);
        buttonDownload.enabled = NO;
    }else{
        buttonDownload.enabled = YES;
    }
    
    //update progress bar
    [self.progressBar setProgress:0.0 animated:animated];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
- (void)simulateClearLocalStorage{
    BIDAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
    NSManagedObjectContext *context = [appDelegate managedObjectContext];
    NSFetchRequest *request1 = [[NSFetchRequest alloc] initWithEntityName:@"Developer"];
    NSError *error;
    NSArray *objects = [context executeFetchRequest:request1 error:&error];
    if (objects == nil){
        NSLog(@"There is an error!");
    }else{
        //NSLog(@"number of developers: %d", [objects count]);
        for (NSManagedObject *object in objects){
            [context deleteObject:object];
        }
    }
    NSFetchRequest *request2 = [[NSFetchRequest alloc] initWithEntityName:@"MonthlyData"];
    objects = [context executeFetchRequest:request2 error:&error];
    if (objects == nil){
        NSLog(@"There is an error!");
    }else{
        //NSLog(@"number of monthly data: %d", [objects count]);
        for (NSManagedObject *object in objects){
            [context deleteObject:object];
        }
    }
    NSFetchRequest *request3 = [[NSFetchRequest alloc] initWithEntityName:@"YearlyData"];
    objects = [context executeFetchRequest:request3 error:&error];
    if (objects == nil){
        NSLog(@"There is an error!");
    }else{
        //NSLog(@"number of monthly data: %d", [objects count]);
        for (NSManagedObject *object in objects){
            [context deleteObject:object];
        }
    }
    [appDelegate saveContext];
}
- (IBAction)clearLocalStorage:(id)sender {
    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Are you sure?" delegate:self cancelButtonTitle:@"No" destructiveButtonTitle:@"Yes" otherButtonTitles:nil];
    [actionSheet showFromTabBar:self.tabBarController.tabBar];
}
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex{
    if (buttonIndex != [actionSheet cancelButtonIndex]){
        [self simulateClearLocalStorage];
        //update progress bar
        [self.progressBar setProgress:0.0];
    }
}

- (IBAction)fetchSvnLogs:(id)sender {
    // init Core Data context
    BIDAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
    NSManagedObjectContext *context = [appDelegate managedObjectContext];
    NSMutableArray *developersName;
    NSInteger numberOfFetchs;
    
    // download protocol implementation: http://code.google.com/p/isvnstat/wiki/DownloadingProtocol
    // 1. get latest revision on SVN
    svn_client_log_ios(1, BID_MAX_COMMITS_PER_CONNECTION, 1, NULL);
    // get latest revision of last download on core data
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Commit"];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"revision" ascending:YES];
    [request setSortDescriptors:@[sortDescriptor]];
    NSError *error;
    NSArray *commits = [context executeFetchRequest:request error:&error];
    NSNumber *lastLastestRevision;
    if (commits != nil){
        if ([commits count] == 0){
            lastLastestRevision = [NSNumber numberWithInt:1];
        }else{
            lastLastestRevision = [commits[[commits count]-1] valueForKey:@"revision"];
        }
    }
    // 2. TODO: select number of revisions per download, in stead of BID_MAX_COMMITS_PER_CONNECTION
    // 3. calculate number of Fetch
    if (((latestRevision-[lastLastestRevision intValue]) % BID_MAX_COMMITS_PER_CONNECTION) == 0){
        numberOfFetchs = (latestRevision-[lastLastestRevision intValue])/BID_MAX_COMMITS_PER_CONNECTION;
    }else{
        numberOfFetchs = (latestRevision-[lastLastestRevision intValue])/BID_MAX_COMMITS_PER_CONNECTION + 1;
    }
    //printf("-------------------------------------\n");
    //printf("number of fetch: %d\n", numberOfFetchs);
    //update progress bar
    [self.progressBar setProgress:0.2];
    for (int i = 0; i < numberOfFetchs; i++){
        // 4. download log
        if (((latestRevision-[lastLastestRevision intValue])-(BID_MAX_COMMITS_PER_CONNECTION*i)) > BID_MAX_COMMITS_PER_CONNECTION){
            svn_client_log_ios(0, latestRevision-(BID_MAX_COMMITS_PER_CONNECTION*i), latestRevision-(BID_MAX_COMMITS_PER_CONNECTION*(i+1)), NULL);
        }else{
            svn_client_log_ios(0, latestRevision-(BID_MAX_COMMITS_PER_CONNECTION*i), [lastLastestRevision intValue], NULL);
        }
        // 5. insert log to Core Data
        for (int j = 0; j < logFetch.numberOfCommits; j++){
            // 5.1 insert comment
            NSManagedObject *comment = [NSEntityDescription insertNewObjectForEntityForName:@"Comment" inManagedObjectContext:context];
            NSString *message = [NSString stringWithUTF8String:logFetch.commits[j].message];
            [comment setValue:message forKey:@"comment"];
            // 5.2 insert files
            NSMutableSet *files = [[NSMutableSet alloc] init];
            for (int k = 0; k < logFetch.commits[j].numberOfChanges; k++){
                NSManagedObject *file = [NSEntityDescription insertNewObjectForEntityForName:@"File" inManagedObjectContext:context];
                NSString *fileValue = [NSString stringWithUTF8String:logFetch.commits[j].changes[k].file];
                [file setValue:fileValue forKey:@"filePath"];
                [files addObject:file];
            }
            // 5.3 insert commit
            NSManagedObject *commit = [NSEntityDescription insertNewObjectForEntityForName:@"Commit" inManagedObjectContext:context];
            [commit setValue:[NSNumber numberWithInt:logFetch.commits[j].revision] forKey:@"revision"];
            NSString *date = [NSString stringWithUTF8String:logFetch.commits[j].date];
            [commit setValue:date forKey:@"dateOfCommit"];
            [commit setValue:comment forKey:@"commitComment"];            
            [commit setValue:files forKey:@"commitFiles"];
            NSString *devName = [NSString stringWithUTF8String:logFetch.commits[j].author];
            [commit setValue:devName forKey:@"developer"];
            // 5.4 insert developer
            // 5.4.1 insert dev name
            NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Developer"];
            NSPredicate *predicate = [NSPredicate predicateWithFormat:
                                      @"(name = %@)",devName];
            [request setPredicate:predicate];
            NSError *error;
            NSArray *objects = [context executeFetchRequest:request error:&error];
            if (objects == nil){
                NSLog(@"There is an error!");
            }else{
                if ([objects count] == 0){
                    //NSLog(@"-----------------------------\n");
                    //NSLog(@"dev name: %@", devName);
                    NSManagedObject *developer = [NSEntityDescription insertNewObjectForEntityForName:@"Developer" inManagedObjectContext:context];
                    [developer setValue:devName forKey:@"name"];
                    NSManagedObject *monthlyData = [NSEntityDescription insertNewObjectForEntityForName:@"MonthlyData" inManagedObjectContext:context];
                    [monthlyData setValue:devName forKey:@"name"];
                    NSManagedObject *yearlyData = [NSEntityDescription insertNewObjectForEntityForName:@"YearlyData" inManagedObjectContext:context];
                    [yearlyData setValue:devName forKey:@"name"];
                    // 5.4.2 set reverse relation for commit
                    [commit setValue:developer forKey:@"commitsDeveloper"];
                }else{
                    [commit setValue:objects[0] forKey:@"commitsDeveloper"];
                }
            }
            // 5.5 calculate monthly/yearlly data for each developer
            // TODO: please consider timezone
            NSDate *today = [NSDate date];
            NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
            NSDateComponents *components = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:today];
            NSInteger currentMonth = [components month];
            NSInteger currentYear = [components year];
            NSArray *strComponents=[[NSString stringWithUTF8String:logFetch.commits[j].date ] componentsSeparatedByString:@"-"];
            //NSLog(@"%s", logFetch.commits[j].date);
            //NSLog(@"from log, year:%@ month:%@ day:%@", strComponents[0], strComponents[1], [strComponents[2] componentsSeparatedByString:@"T"][0]);
            //NSLog(@"from machine, year:%d month:%d", currentYear, currentMonth);
            if (currentYear == [strComponents[0] intValue]){
                NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"YearlyData"];
                NSPredicate *predicate = [NSPredicate predicateWithFormat:
                                          @"(name = %@)",devName];
                [request setPredicate:predicate];
                NSArray *objects = [context executeFetchRequest:request error:&error];
                if (objects != nil){
                    //NSLog(@"current var:%@", [objects[0] valueForKey:[NSString stringWithFormat:@"m%@",strComponents[1]]]);
                    NSNumber *currentVar = [objects[0] valueForKey:[NSString stringWithFormat:@"m%@",strComponents[1]]];
                    [objects[0] setValue:[NSNumber numberWithInt:[currentVar intValue]+1] forKey:[NSString stringWithFormat:@"m%@",strComponents[1]]];
                }
                if (currentMonth == [strComponents[1] intValue]){
                    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"MonthlyData"];
                    NSPredicate *predicate = [NSPredicate predicateWithFormat:
                                              @"(name = %@)",devName];
                    [request setPredicate:predicate];
                    NSArray *objects = [context executeFetchRequest:request error:&error];
                    if (objects != nil){
                        NSString *day =[strComponents[2] componentsSeparatedByString:@"T"][0];
                        NSNumber *currentVar = [objects[0] valueForKey:[NSString stringWithFormat:@"d%@",day]];
                        [objects[0] setValue:[NSNumber numberWithInt:[currentVar intValue]+1] forKey:[NSString stringWithFormat:@"d%@",day]];
                    }
                }
            }
            [appDelegate saveContext];
        }
    }
    [appDelegate saveContext];
    //update progress bar
    [self.progressBar setProgress:1.0];
}
@end
